#ifndef NODE_H
#define NODE_H

#include "structs.h"
#include "Element.h"

#include <QObject>
#include <QDeclarativeItem>

class Root;

class Node : public QObject
{
    Q_OBJECT
protected:
    // list - массив сожержащий объекты класса Element,
    // т.е. это уже массив указателей на подуровни + массив элементов.
    vector<Elem> list;
    // count - количество элементов в list-те с учетом
    // нулевого элемента, в котором содержится только указатель
    // на подуровень (на эл., меньшие самого меньшего в узле)
    int count;
    // указатель на родительский узел
    Node* parent;
    /**************************************************************/

    /***методы для вставки элементов (split - раскол узла)***/
    bool vector_insert (Elem& element, bool isSplitInsert);
    bool split_insert (Elem& element);
    void insert_zeroth_subtree (Node* subtree);

    /****удаление элементов с узла****/
    bool vector_delete (Elem& target);
    bool vector_delete (int target_pos);

    Node* right_sibling (int& parent_index_this);
    Node* left_sibling (int& parent_index_this);

    /****переливания с левым или правым узлом****/
    Node* rotate_from_left(int parent_index_this);
    Node* rotate_from_right(int parent_index_this);

    /****слияние с правым или левым узлом****/
    Node* merge_right (int parent_index_this);
    Node* merge_left (int parent_index_this);

    /****вспомогальные методы, названия говорят сами за себя:) ****/
    int key_count () { return count-1; }
    Elem& largest_key () { return list[count-1]; }
    Elem& smallest_key () { return list[1]; }

    Elem& smallest_key_in_subtree();
    // минимальное количество элементов в узле
    int min_keys ();
    bool is_leaf();

signals:
    // TODO: emit
    void nodeCreated(Node* newNode);
    void nodeChanged(Node* node);
    void fatherChanged(Node* node);
    void nodeDestroyed(Node* node);

public:
    Elem& search (Elem& desired, Node*& last_visited);
    bool tree_insert (Elem& element);
    bool delete_element (Elem& target);
    int delete_all_subtrees ();
    Node* find_root();
    Elem& operator[] (int i) { return list[i]; }

    // при неудачном поиске возвращаем ссылку на fail.
    static Elem fail;
    Root& root;
    Node (Root& root_track);
    void dump ();

    // for interface (говнокод)
    QDeclarativeItem* getQNode() const { return mQNode; }
    void setQNode(QDeclarativeItem* qNode) { mQNode = qNode; }

    Node* getFather() const;
    void setFather(Node* father);

    int getCount() const;
    int getParentIndex ();

private:
    QDeclarativeItem *mQNode;
};

#endif // NODE_H
